CREATING AN INTERACTIVE HORIZON SURFACES PLOT¶

Introduction¶

A horizon surface is the boundary between different geological layers or formations in the subsurface. It represents stratigraphic or lithological changes and is used for visualizing and analyzing subsurface structure through two-dimensional maps or three-dimensional models.

About the Data: Horizon Surface Datasets from the Volve Dataset's Geophysical Interpretations Folder¶

BCU, Hugin Fm Base, Hugin Fm Top, Shetland GP Top, and Ty Fm Top are distinct horizon surface datasets from the Volve dataset's Geophysical Interpretations folder, provided in CSV file format.

Python Codes behind the generated interactive horizon surface plot¶

To ensure smooth data processing and visualization, we import the following important Python libraries in this code process:

  • NumPy: A powerful library for efficient numerical computations and data manipulation.
  • Pandas: Provides versatile capabilities for seamless data manipulation and analysis.
  • Plotly Express: Simplifies the creation of interactive plots and visualizations.
  • Plotly Graph Objects: Offers advanced features for customized visualizations.
  • Path from pathlib: Facilitates easy management of file paths and directories.
  • Plot from plotly.offline: Enables the generation of offline plots saved as HTML files.
  • griddata from scipy.interpolate: Provides functions for data interpolation.

By using these libraries, we enhance data operations, create attractive visualizations with ease, handle file paths and directories conveniently, and perform data interpolation in our code.

In [1]:
# Import python libraries
import numpy as np
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from pathlib import Path
from plotly.offline import plot
from scipy.interpolate import griddata

In the following codes below, we import data files and assign them to variables using the specified file paths:

  • First, we define the file path using Path.cwd().joinpath("horizon"), which represents the "horizon" directory in the current working directory. This allows us to specify the location of the data files we want to import.
  • Second, we import the data files "BCU.csv", "Hugin_Fm_Base.csv", "Hugin_Fm_Top.csv", "Shetland_GP_Top.csv", and "Ty_Fm_Top.csv" using the pd.read_csv() function of Pandas library and the appropriate file paths.
  • Third, the imported data files are now assigned to the variables bcu, hugin_base, hugin_top, shetland_top, and ty_top, respectively.

So, we can now access and analyze their data within the code by using the specified file paths and importing the data files.

In [2]:
# Importing Data Files
paths = Path.cwd().joinpath("horizon")
bcu = pd.read_csv("BCU.csv")
hugin_base = pd.read_csv("Hugin_Fm_Base.csv")
hugin_top = pd.read_csv("Hugin_Fm_Top.csv")
shetland_top = pd.read_csv("Shetland_GP_Top.csv")
ty_top = pd.read_csv("Ty_Fm_Top.csv")

Moving on to the next set of code lines, we regrid the data for visualization.

  • We determine the grid density by adjusting the step variable. Increasing the step value creates a denser grid with more points, capturing finer details in the plot. Decreasing the step value produces a sparser grid with fewer points, simplifying the plot. In this case, we set the step value to "64". Note that choosing the appropriate step value depends on the specific dataset and the desired level of detail in the visualization.
  • Then, we create a grid by connecting the x and y coordinates from the bcu data. This grid has a fixed number of points in both the x and y directions.
  • To ensure accurate regridding, we use a technique called interpolation with a cubic method. This method calculates smooth values for missing data points, improving the visual representation and analysis of the data.
  • Afterwards, we apply the regridding process to each DataFrame (bcu, hugin_base, hugin_top, shetland_top, and ty_top) using a list comprehension. This generates a list of regridded z-values for each DataFrame.
  • The regridded z-values are stored in variables: bcu_z, hugin_base_z, hugin_top_z, shetland_top_z, and ty_top_z. By converting the irregularly spaced data points into a regular grid, we enhance the effectiveness of data visualization and analysis.
In [3]:
# Regridding Data for Visualization
step = 64
xi, yi = np.meshgrid(np.linspace(bcu["X"].min(), bcu["X"].max(), step), np.linspace(bcu["Y"].min(), bcu["Y"].max(), step))
regrid_data = lambda df: griddata((df["X"], df["Y"]), df["Z"], (xi, yi), method="cubic")
bcu_z, hugin_base_z, hugin_top_z, shetland_top_z, ty_top_z = [regrid_data(df) 
                                                              for df in [bcu, hugin_base, hugin_top,shetland_top, ty_top]]

The following code calculates the range of values for the z-axis in order to properly visualize the data.

  • We find the maximum value among the regridded z-values from the different data frames (bcu_z, hugin_base_z, hugin_top_z, shetland_top_z, and ty_top_z). Since we want to display the data in a specific orientation, we take the negative of this maximum value.
  • Similarly, we find the minimum value among the regridded z-values. Again, we take the negative of this minimum value.

By taking the negative values, we ensure that the z-axis range is aligned with our visualization requirements. The resulting z_min and z_max values represent the computed range of the z-axis. These values can be used to set appropriate limits for the z-axis in the plot, ensuring that all the data points are accurately represented.

In [4]:
# Computing Z-axis Range
z_min = -np.nanmax(np.r_[bcu_z, hugin_base_z, hugin_top_z, shetland_top_z, ty_top_z])
z_max = -np.nanmin(np.r_[bcu_z, hugin_base_z, hugin_top_z, shetland_top_z, ty_top_z])

Let's proceed. We create surface plots to visualize different datasets. In the code below, each dataset represents a different aspect of the data we are analyzing. We use the Plotly library to create these surface plots. The surface plot shows the data in a three-dimensional form, where the height of the surface represents the values of the dataset. To create the plots, we specify the x and y coordinates based on a grid, and the z-values are determined by the regridded data we obtained earlier. We assign a specific color scale to each dataset, which helps us distinguish and compare them visually. The color scale represents the range of values in the dataset, with higher values shown in one color and lower values in another. By creating these surface plots, we can easily understand and analyze the different datasets in a visually appealing way, gaining insights into the underlying patterns and variations in the data.

In [5]:
# Creating Surface Plots for Each Dataset
bcu_surface = go.Surface(z=-bcu_z, x=xi, y=yi, colorscale='Jet', cmin=z_min, cmax=z_max, name='BCU')
hugin_base_surface = go.Surface(z=-hugin_base_z, x=xi, y=yi, colorscale='Viridis', cmin=z_min, cmax=z_max, 
                                name='Hugin Fm Base')
hugin_top_surface = go.Surface(z=-hugin_top_z, x=xi, y=yi, colorscale='Rainbow', cmin=z_min, cmax=z_max, 
                               name='Hugin Fm Top')
shetland_top_surface = go.Surface(z=-shetland_top_z, x=xi, y=yi, colorscale='Hot', cmin=z_min, cmax=z_max, 
                                  name='Shetland GP Top')
ty_top_surface = go.Surface(z=-ty_top_z, x=xi, y=yi, colorscale='Electric', cmin=z_min, cmax=z_max, name='Ty Fm Top')

For the last part of this code process, the code below creates an interactive horizon plot using Plotly to visualize the Volve horizons in a 3D surface plot. The plot combines surface plots for each dataset representing different geological horizons: bcu, hugin_base, hugin_top, shetland_top, and ty_top.

Customization options are applied to enhance the plot's appearance and interactivity. The layout is adjusted with a title that includes the location information. The plot's dimensions, margins, legend, and hover mode are set accordingly.

The scene settings define the aspect ratio and provide titles for the x, y, and z axes. Further, the initial camera position is specified to optimize the view.

Once the horizon plot is created, it is displayed and can be interacted with. At last, we display the horizon plot and save it as an HTML file for further use or sharing. The html file of the interactive horizon surfaces plot is available on the github repository for viewing.

In [6]:
# Creating the Horizon Plot
horizon = go.Figure(data=[bcu_surface, hugin_base_surface, hugin_top_surface, shetland_top_surface, ty_top_surface])

# Customizing the Horizon Plot
horizon.update_layout(title=dict(text="VISUALIZING VOLVE HORIZONS - INTERACTIVE SURFACE PLOT<br>Location: NORTH SEA",
                                 x=0.5, # Set the x position to center the title
                                 xanchor='center'),  # Center the title horizontally
    width=1200,
    height=700,
    margin=dict(l=20, r=20, b=20, t=80),
    showlegend=True,
    hovermode='closest',
    scene=dict(aspectratio=dict(x=1, y=1, z=0.7),  # Adjust the aspect ratio of the scene
               xaxis=dict(title='X COORDINATE'), yaxis=dict(title='Y COORDINATE'), zaxis=dict(title='TOTAL DEPTH'),
               camera=dict(eye=dict(x=1.2, y=1.2, z=0.8)))) # Set the initial camera position

# Show the horizon plot to visualize the Volve horizons in a 3D surface plot
horizon.show()

# Save the plot as an HTML file
plot(horizon, filename='Volve Horizon Surfaces.html')
Out[6]:
'Volve Horizon Surfaces.html'

Data Credits¶

Equinor ASA (formerly Statoil) and the former Volve license partners, ExxonMobil Exploration & Production Norway AS and Bayerngas Norge AS, are credited for providing the VOLVE dataset under CC BY 4.0 license.

Thank You for Visiting This GitHub Repository: Grateful for Your Interest¶

Thank you so much for visiting this GitHub repository and taking the time to read this notebook. I hope you found it informative and learned something new. Your support and interest are sincerely appreciated.